home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
tcp_ip
/
ntp_src
/
ntp_util.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-03
|
21KB
|
1,149 lines
/* $Header: ntp_util.c,v 1.3 91/06/19 11:08:09 ath Exp $ */
/*
* ntp_util.c - stuff I didn't have any other place for
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "global.h"
#include "sockaddr.h"
#include "mbuf.h" /* for {get,put}{16,32} */
#include "netuser.h"
#include "ntp_types.h"
#include "ntp_syslog.h"
#include "ntp_fp.h"
#include "ntp.h"
#include "ntp_calendar.h"
/*
* This contains odds and ends. Right now the only thing you'll find
* in here is the hourly stats printer and some code to support rereading
* the keys file, but I may eventually put other things in here such as
* code to do something with the leap bits.
*/
#ifdef XNTP_AUTHENTICATE
/*
* Name of the keys file
*/
char *key_file_name;
#endif /* XNTP_AUTHENTICATE */
#if 0 /* No drift file right now */
/*
* The name of the drift_comp file and the temporary.
*/
char *stats_drift_file;
char *stats_temp_file;
#endif /* 0 */
/*
* We query the errno to see what kind of error occured
* when opening the drift file.
*/
extern int errno;
#ifdef DEBUG
extern int debug;
#endif
/*
* init_util - initialize the utilities
*/
void
init_util()
{
#if 0
stats_drift_file = 0;
stats_temp_file = 0;
#endif /* 0 */
#ifdef XNTP_AUTHENTICATE
key_file_name = 0;
#endif
}
/*
* hourly_stats - print some interesting stats
*/
void
hourly_stats()
{
int fd;
char *val;
int vallen;
extern l_fp drift_comp;
extern long compliance;
extern char *lfptoa();
extern char *mfptoa();
syslog(LOG_INFO, "hourly check: drift %s compliance %s",
lfptoa(&drift_comp, 8),
mfptoa((compliance<0)?(-1L):0L, compliance, 8));
#if 0 /* no drift file for now in NOS */
if (stats_drift_file != 0) {
fd = open(stats_temp_file, O_WRONLY|O_TRUNC|O_CREAT, 0666);
if (fd == -1) {
syslog(LOG_ERR, "can't open %s: %m", stats_temp_file);
return;
}
val = lfptoa(&drift_comp, 9);
vallen = strlen(val);
/*
* Hack here. Turn the trailing \0 into a \n and write it.
*/
val[vallen] = '\n';
if (write(fd, val, vallen+1) == -1) {
syslog(LOG_ERR, "write to %s failed: %m",
stats_temp_file);
(void) close(fd);
(void) unlink(stats_temp_file);
} else {
(void) close(fd);
/* atomic */
(void) rename(stats_temp_file, stats_drift_file);
}
}
#endif /* 0 */
}
/*
* stats_config - configure the stats operation
*/
void
stats_config(item, value)
int item;
char *value; /* only one type so far */
{
register char *cp;
FILE *fp;
int len;
/* char buf[128]; */
l_fp old_drift;
extern void loop_config();
extern char *lfptoa();
switch(item) {
#if 0 /* no drift file yet. */
case STATS_FREQ_FILE:
if (stats_drift_file != 0) {
(void) free(stats_drift_file);
(void) free(stats_temp_file);
stats_drift_file = 0;
stats_temp_file = 0;
}
if (value == 0 || (len = strlen(value)) == 0)
break;
stats_drift_file = emalloc((u_int)(len + 1));
stats_temp_file = emalloc((u_int)(len + sizeof(".TEMP")));
bcopy(value, stats_drift_file, len+1);
bcopy(value, stats_temp_file, len);
bcopy(".TEMP", stats_temp_file + len, sizeof(".TEMP"));
#ifdef DEBUG
if (debug > 1) {
printf("stats drift file %s\n", stats_drift_file);
printf("stats temp file %s\n", stats_temp_file);
}
#endif
if ((fp = fopen(stats_drift_file, "r")) == NULL) {
if (errno != ENOENT)
syslog(LOG_ERR, "can't open %s: %m",
stats_drift_file);
break;
}
if (fgets(buf, sizeof buf, fp) == NULL) {
syslog(LOG_ERR, "can't read %s: %m",
stats_drift_file);
(void) fclose(fp);
break;
}
(void) fclose(fp);
/*
* We allow leading spaces, then the number. Terminate
* at any trailing space or string terminator.
*/
cp = buf;
while (isspace(*cp))
cp++;
while (*cp != '\0' && !isspace(*cp))
cp++;
*cp = '\0';
if (!atolfp(buf, &old_drift)) {
syslog(LOG_ERR, "drift value %s invalid", buf);
break;
}
/*
* Finally! Give value to the loop filter.
*/
#ifdef DEBUG
if (debug > 1) {
printf("loop_config finds old drift of %s\n",
lfptoa(&old_drift, 9));
}
#endif
loop_config(LOOP_DRIFTCOMP, &old_drift);
break;
#endif /* 0 */
/* The drift value itself is passed in. */
case STATS_FREQ:
if (!atolfp(value, &old_drift)) {
tprintf("drift value %s invalid", value);
break;
}
loop_config(LOOP_DRIFTCOMP, &old_drift);
break;
default:
/* oh well */
break;
}
}
#ifdef XNTP_AUTHENTICATE
/*
* getauthkeys - read the authentication keys from the specified file
*/
void
getauthkeys(keyfile)
char *keyfile;
{
int len;
len = strlen(keyfile);
if (len == 0)
return;
if (key_file_name != 0) {
if (len > strlen(key_file_name)) {
(void) free(key_file_name);
key_file_name = 0;
}
}
if (key_file_name == 0)
key_file_name = mallocw((u_int)(len + 1));
bcopy(keyfile, key_file_name, len+1);
authreadkeys(key_file_name);
}
/*
* rereadkeys - read the authentication key file over again.
*/
void
rereadkeys()
{
if (key_file_name != 0)
authreadkeys(key_file_name);
}
#endif /* XNTP_AUTHENTICATE */
/* htons and friends, implemented using the equivalent NOS functions. */
int16
htons (h)
int16 h;
{
int16 n;
put16 ((char *)&n, h);
return n;
}
int16
ntohs (n)
int16 n;
{
return get16 ((char *)&n);
}
int32
htonl (h)
int32 h;
{
int32 n;
put32 ((char *)&n, h);
return n;
}
int32
ntohl (n)
int32 n;
{
return get32 ((char *)&n);
}
/*
* And here we have all the routines used by the NOS ntp code from xntp's
* library. I didn't want to make yet another library for NOS.
*/
/******
* ranny.c
*/
/*
* Random number generator is:
*
* Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
* This will be free software, but only when it is finished.
*
* Used in xntp by permission of the author. If copyright is
* annoying to you, read no further. Instead, look up the reference,
* write me an equivalent to this and send it back to me.
*/
/*
* Random number generator; see Knuth Vol 2. 2nd ed. p.27 (section 3.2.2)
*/
/*
* 55 random numbers, not all even. Note we don't initialize ran_y
* directly since I have had thoughts of putting this in an EPROM
*/
static u_long ran_y[55];
static u_long init_ran_y[55] = {
1860909544, 231033423, 437666411, 1349655137, 2014584962,
504613712, 656256107, 1246027206, 573713775, 643466871,
540235388, 1630565153, 443649364, 729302839, 1933991552,
944681982, 949111118, 406212522, 1065063137, 1712954727,
73280612, 787623973, 1874130997, 801658492, 73395958,
739165367, 596047144, 490055249, 1131094323, 662727104,
483614097, 844520219, 893760527, 921280508, 46691708,
760861842, 1425894220, 702947816, 2006889048, 1999607995,
1346414687, 399640789, 1482689501, 1790064052, 1128943628,
1269197405, 587262386, 2078054746, 1675409928, 1652325524,
1643525825, 1748690540, 292465849, 1370173174, 402865384
};
static int ran_j;
static int ran_k;
/*
* ranp2 - return a random integer in the range 0 .. (1<<m)-1
*/
u_long
ranp2(m)
int m;
{
u_long r;
ran_y[ran_k] += ran_y[ran_j]; /* overflow does a mod */
r = ran_y[ran_k];
if (ran_k-- == 0) ran_k = 54;
if (ran_j-- == 0) ran_j = 54;
return (r & ((1<<m)-1));
}
#ifdef notdef
/*
* ranny - return a random integer in the range 0 .. m-1
*/
u_long
ranny(m)
u_int m;
{
unsigned long r;
ran_y[ran_k] += ran_y[ran_j]; /* overflow does a mod */
r = ran_y[ran_k];
if (ran_k-- == 0) ran_k = 54;
if (ran_j-- == 0) ran_j = 54;
return (r % m);
}
#endif /* notdef */
/*
* init_random - do initialization of random number routine
*/
void
init_random()
{
register int i;
register time_t now;
ran_j = 23;
ran_k = 54;
/*
* Randomize the seed array some more. The time of day
* should be initialized by now.
*/
now = (time_t)(time((time_t *)0))|01;
for (i = 0; i < 55; ++i)
ran_y[i] = now * init_ran_y[i]; /* overflow does a mod */
}
/* ntp passes ntoa a pointer to a sockaddr_in, and wants a char * back.
* NOS has inet_ntoa() which takes a long (in host byte order) and returns a
* char *.
*/
char *
ntoa(addr)
struct sockaddr_in *addr;
{
return inet_ntoa (ntohl (addr->sin_addr.s_addr));
}
/*
* lib_strbuf.h - definitions for routines which use the common string buffers
*/
/*
* Sizes of things
*/
#define LIB_NUMBUFS 5
#define LIB_BUFLENGTH 80
/*
* Macro to get a pointer to the next buffer
*/
#define LIB_GETBUF(buf) \
do { \
buf = &lib_stringbuf[lib_nextbuf][0]; \
if (++lib_nextbuf >= LIB_NUMBUFS) \
lib_nextbuf = 0; \
} while (0)
/*
* lib_strbuf - library string storage
*/
/*
* Storage declarations
*/
char lib_stringbuf[LIB_NUMBUFS][LIB_BUFLENGTH];
int lib_nextbuf;
/*
* initialization routine. Might be needed if the code is ROMized.
*/
void
init_lib()
{
lib_nextbuf = 0;
}
/*
* lfptoa - return an asciized representation of a signed l_fp number
*/
char *
lfptoa(fpv, ndec)
l_fp *fpv;
int ndec;
{
extern char *mfptoa();
return mfptoa(fpv->l_ui, fpv->l_uf, ndec);
}
/*
* atolfp - convert an ascii string to an l_fp number
*/
/*
* Powers of 10
*/
static u_long ten_to_the_n[10] = {
0,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
};
int
atolfp(str, lfp)
char *str;
l_fp *lfp;
{
register char *cp;
register u_long dec_i;
register u_long dec_f;
char *ind;
int ndec;
int isneg;
static char *digits = "0123456789";
isneg = 0;
dec_i = dec_f = 0;
ndec = 0;
cp = str;
/*
* We understand numbers of the form:
*
* [spaces][-][digits][.][digits][spaces|\n|\0]
*/
while (isspace(*cp))
cp++;
if (*cp == '-') {
cp++;
isneg = 1;
}
/* gdt */
if (*cp == '+') {
cp++;
isneg = 0;
}
if (*cp != '.' && !isdigit(*cp))
return 0;
#define index strchr /* ANSI C */
while (*cp != '\0' && (ind = index(digits, *cp)) != NULL) {
dec_i = (dec_i << 3) + (dec_i << 1); /* multiply by 10 */
dec_i += (ind - digits);
cp++;
}
if (*cp != '\0' && !isspace(*cp)) {
if (*cp++ != '.')
return 0;
while (ndec < 9 && *cp != '\0'
&& (ind = index(digits, *cp)) != NULL) {
ndec++;
dec_f = (dec_f << 3) + (dec_f << 1); /* *10 */
dec_f += (ind - digits);
cp++;
}
while (isdigit(*cp))
cp++;
if (*cp != '\0' && !isspace(*cp))
return 0;
}
if (ndec > 0) {
register u_long tmp;
register u_long bit;
register u_long ten_fact;
ten_fact = ten_to_the_n[ndec];
tmp = 0;
bit = 0x80000000;
while (bit != 0) {
dec_f <<= 1;
if (dec_f >= ten_fact) {
tmp |= bit;
dec_f -= ten_fact;
}
bit >>= 1;
}
if ((dec_f << 1) > ten_fact)
tmp++;
dec_f = tmp;
}
if (isneg)
M_NEG(dec_i, dec_f);
lfp->l_ui = dec_i;
lfp->l_uf = dec_f;
return 1;
}
/*
* umfptoa - Return an asciized representation of an unsigned long fp number
*/
char *
umfptoa(fpi, fpf, ndec)
u_long fpi;
u_long fpf;
int ndec;
{
extern char *dolfptoa();
return dolfptoa(fpi, fpf, 0, ndec, 0);
}
/*
* mfptoa - Return an asciized representation of a signed long fp number
*/
char *
mfptoa(fpi, fpf, ndec)
u_long fpi;
u_long fpf;
int ndec;
{
int isneg;
extern char *dolfptoa();
if (M_ISNEG(fpi, fpf)) {
isneg = 1;
M_NEG(fpi, fpf);
} else
isneg = 0;
return dolfptoa(fpi, fpf, isneg, ndec, 0);
}
/*
* fptoa - return an asciized representation of an s_fp number
*/
char *
fptoa(fpv, ndec)
s_fp fpv;
int ndec;
{
u_fp plusfp;
int neg;
extern char *dofptoa();
if (fpv < 0) {
plusfp = (u_fp)(-fpv);
neg = 1;
} else {
plusfp = (u_fp)fpv;
neg = 0;
}
return dofptoa(plusfp, neg, ndec, 0);
}
/*
* ufptoa - return an asciized representation of an u_fp number
*/
char *
ufptoa(fpv, ndec)
u_fp fpv;
int ndec;
{
extern char *dofptoa();
return dofptoa(fpv, 0, ndec, 0);
}
/*
* ufptoms - return an asciized u_fp number in milliseconds
*/
char *
ufptoms(fpv, ndec)
u_fp fpv;
int ndec;
{
extern char *dofptoa();
return dofptoa(fpv, 0, ndec, 1);
}
/*
* ulfptoms - return an asciized unsigned l_fp number in milliseconds
*/
char *
ulfptoms(fpv, ndec)
l_fp *fpv;
int ndec;
{
extern char *umfptoms();
return umfptoms(fpv->l_ui, fpv->l_uf, ndec);
}
/*
* lfptoms - return an asciized signed l_fp number in milliseconds
*/
char *
lfptoms(fpv, ndec)
l_fp *fpv;
int ndec;
{
extern char *mfptoms();
return mfptoms(fpv->l_ui, fpv->l_uf, ndec);
}
/*
* fptoms - return an asciized s_fp number in milliseconds
*/
char *
fptoms(fpv, ndec)
s_fp fpv;
int ndec;
{
u_fp plusfp;
int neg;
extern char *dofptoa();
if (fpv < 0) {
plusfp = (u_fp)(-fpv);
neg = 1;
} else {
plusfp = (u_fp)fpv;
neg = 0;
}
return dofptoa(plusfp, neg, ndec, 1);
}
/*
* numtoa - return asciized network numbers store in local array space
*/
char *
numtoa(num)
u_long num;
{
register u_long netnum;
register char *buf;
netnum = ntohl(num);
LIB_GETBUF(buf);
(void) sprintf(buf, "%d.%d.%d.%d", (int)((netnum>>24)&0xff),
(int)((netnum>>16)&0xff), (int)((netnum>>8)&0xff),
(int)(netnum&0xff));
return buf;
}
/*
* atoint - convert an ascii string to a signed long, with error checking
*/
int
atoint(str, ival)
char *str;
long *ival;
{
register u_long u;
register char *cp;
register int isneg;
register int oflow_digit;
cp = str;
if (*cp == '-') {
cp++;
isneg = 1;
oflow_digit = '8';
} else {
isneg = 0;
oflow_digit = '7';
}
if (*cp == '\0')
return 0;
u = 0;
while (*cp != '\0') {
if (!isdigit(*cp))
return 0;
if (u > 214748364 || (u == 214748364 && *cp > oflow_digit))
return 0; /* overflow */
u = (u << 3) + (u << 1);
u += *cp++ - '0'; /* ascii dependent */
}
if (isneg)
*ival = -((long)u);
else
*ival = (long)u;
return 1;
}
/*
* mfptoms - Return an asciized signed long fp number in milliseconds
*/
char *
mfptoms(fpi, fpf, ndec)
u_long fpi;
u_long fpf;
int ndec;
{
int isneg;
extern char *dolfptoa();
if (M_ISNEG(fpi, fpf)) {
isneg = 1;
M_NEG(fpi, fpf);
} else
isneg = 0;
return dolfptoa(fpi, fpf, isneg, ndec, 1);
}
/*
* umfptoms - Return an asciized unsigned long fp number in milliseconds
*/
char *
umfptoms(fpi, fpf, ndec)
u_long fpi;
u_long fpf;
int ndec;
{
extern char *dolfptoa();
return dolfptoa(fpi, fpf, 0, ndec, 1);
}
/*
* dolfptoa - do the grunge work of converting an l_fp number to decimal
*/
char *
dolfptoa(fpi, fpv, neg, ndec, msec)
u_long fpi;
u_long fpv;
int neg;
int ndec;
int msec;
{
register u_char *cp, *cpend;
register u_long work_i;
register int dec;
u_char cbuf[24];
u_char *cpdec;
char *buf;
char *bp;
/*
* Get a string buffer before starting
*/
LIB_GETBUF(buf);
/*
* Zero the character buffer
*/
bzero(cbuf, sizeof(cbuf));
/*
* Work on the integral part. This is biased by what I know
* compiles fairly well for a 68000.
*/
cp = cpend = &cbuf[10];
work_i = fpi;
if (work_i & 0xffff0000) {
register u_long lten = 10;
register u_long ltmp;
do {
ltmp = work_i;
work_i /= lten;
ltmp -= (work_i<<3) + (work_i<<1);
*--cp = (u_char)ltmp;
} while (work_i & 0xffff0000);
}
if (work_i != 0) {
register u_short sten = 10;
register u_short stmp;
register u_short swork = (u_short)work_i;
do {
stmp = swork;
swork /= sten;
stmp -= (swork<<3) + (swork<<1);
*--cp = (u_char)stmp;
} while (swork != 0);
}
/*
* Done that, now deal with the problem of the fraction. First
* determine the number of decimal places.
*/
if (msec) {
dec = ndec + 3;
if (dec < 3)
dec = 3;
cpdec = &cbuf[13];
} else {
dec = ndec;
if (dec < 0)
dec = 0;
cpdec = &cbuf[10];
}
if (dec > 12)
dec = 12;
/*
* If there's a fraction to deal with, do so.
*/
if (fpv != 0) {
register u_long work_f;
work_f = fpv;
while (dec > 0) {
register u_long tmp_i;
register u_long tmp_f;
dec--;
/*
* The scheme here is to multiply the
* fraction (0.1234...) by ten. This moves
* a junk of BCD into the units part.
* record that and iterate.
*/
work_i = 0;
M_LSHIFT(work_i, work_f);
tmp_i = work_i;
tmp_f = work_f;
M_LSHIFT(work_i, work_f);
M_LSHIFT(work_i, work_f);
M_ADD(work_i, work_f, tmp_i, tmp_f);
*cpend++ = (u_char)work_i;
if (work_f == 0)
break;
}
/*
* Rounding is rotten
*/
if (work_f & 0x80000000) {
register u_char *tp = cpend;
*(--tp) += 1;
while (*tp >= 10) {
*tp = 0;
*(--tp) += 1;
};
if (tp < cp)
cp = tp;
}
}
cpend += dec;
/*
* We've now got the fraction in cbuf[], with cp pointing at
* the first character, cpend pointing past the last, and
* cpdec pointing at the first character past the decimal.
* Remove leading zeros, then format the number into the
* buffer.
*/
while (cp < cpdec) {
if (*cp != 0)
break;
cp++;
}
if (cp == cpdec)
--cp;
bp = buf;
if (neg)
*bp++ = '-';
while (cp < cpend) {
if (cp == cpdec)
*bp++ = '.';
*bp++ = (char)(*cp++ + '0'); /* ascii dependent? */
}
*bp = '\0';
/*
* Done!
*/
return buf;
}
/*
* dofptoa - do the grunge work to convert an fp number to ascii
*/
char *
dofptoa(fpv, neg, ndec, msec)
u_fp fpv;
int neg;
int ndec;
int msec;
{
register u_char *cp, *cpend;
register u_long val;
register short dec;
u_char cbuf[12];
u_char *cpdec;
char *buf;
char *bp;
/*
* Get a string buffer before starting
*/
LIB_GETBUF(buf);
/*
* Zero out the buffer
*/
bzero((char *)cbuf, sizeof cbuf);
/*
* Set the pointers to point at the first
* decimal place. Get a local copy of the value.
*/
cp = cpend = &cbuf[5];
val = fpv;
/*
* If we have to, decode the integral part
*/
if (!(val & 0xffff0000))
cp--;
else {
register u_short sv = (u_short)(val >> 16);
register u_short tmp;
register u_short ten = 10;
do {
tmp = sv;
sv /= ten;
*(--cp) = tmp - ((sv<<3) + (sv<<1));
} while (sv != 0);
}
/*
* Figure out how much of the fraction to do
*/
if (msec) {
dec = ndec + 3;
if (dec < 3)
dec = 3;
cpdec = &cbuf[8];
} else {
dec = ndec;
cpdec = cpend;
}
if (dec > 6)
dec = 6;
if (dec > 0) {
do {
val &= 0xffff;
val = (val << 3) + (val << 1);
*cpend++ = (u_char)(val >> 16);
} while (--dec > 0);
}
if (val & 0x8000) {
register u_char *tp;
/*
* Round it. Ick.
*/
tp = cpend;
*(--tp) += 1;
while (*tp >= 10) {
*tp = 0;
*(--tp) += 1;
}
}
/*
* Remove leading zeroes if necessary
*/
while (cp < (cpdec -1) && *cp == 0)
cp++;
/*
* Copy it into the buffer, asciizing as we go.
*/
bp = buf;
if (neg)
*bp++ = '-';
while (cp < cpend) {
if (cp == cpdec)
*bp++ = '.';
*bp++ = (char)(*cp++ + '0');
}
*bp = '\0';
return buf;
}
/*
* calleapwhen - determine the number of seconds to the next possible
* leap occurance and the last one.
*/
/*
* calleaptab - leaps occur at the end of December and June
*/
static long calleaptab[10] = {
-(JAN+FEBLEAP)*SECSPERDAY, /* leap previous to cycle */
(MAR+APR+MAY+JUN)*SECSPERDAY, /* end of June */
(MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY, /* end of Dec */
(MAR+APR+MAY+JUN)*SECSPERDAY + SECSPERYEAR,
(MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY + SECSPERYEAR,
(MAR+APR+MAY+JUN)*SECSPERDAY + 2*SECSPERYEAR,
(MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY + 2*SECSPERYEAR,
(MAR+APR+MAY+JUN)*SECSPERDAY + 3*SECSPERYEAR,
(MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY + 3*SECSPERYEAR,
(MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC+JAN+FEBLEAP+MAR+APR+MAY+JUN)
*SECSPERDAY + 3*SECSPERYEAR, /* next after current cycle */
};
void
calleapwhen(ntpdate, leaplast, leapnext)
u_long ntpdate;
u_long *leaplast;
u_long *leapnext;
{
register u_long dateincycle;
register int i;
/*
* Find the offset from the start of the cycle
*/
dateincycle = ntpdate;
if (dateincycle >= MAR1988)
dateincycle -= MAR1988;
else
dateincycle -= MAR1900;
while (dateincycle >= SECSPERCYCLE)
dateincycle -= SECSPERCYCLE;
/*
* Find where we are with respect to the leap events.
*/
for (i = 1; i < 9; i++)
if (dateincycle < (u_long)calleaptab[i])
break;
/*
* i points at the next leap. Compute the last and the next.
*/
*leaplast = (u_long)((long)dateincycle - calleaptab[i-1]);
*leapnext = (u_long)(calleaptab[i] - (long)dateincycle);
}